/*
 * Copyright (C) 2009 The Antilapka Project Team ( antilapka@googlegroups.com )
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cz.dnk.android.gug.antilapka;

//import org.openintents.hardware.SensorManagerSimulator; 
//import org.openintents.provider.Hardware;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import android.preference.PreferenceManager;
import java.lang.Math;


/**
 * Intents:
 * 		boolean cz.dnk.gug.android.antilapka.Activate
 * 		boolean cz.dnk.gug.android.antilapka.ReloadSettings
 * 		boolean cz.dnk.gug.android.antilapka.Fire
 * 
 * The actual ringing is done in onSensorChanged function
 *
 */
public class AntiLapkaService extends Service implements SensorEventListener{
	private static final int ARMED = 1;
	private NotificationManager mNM;
	private SensorManager mSensorManager;
	private PowerManager mPowerManager;
	private PowerManager.WakeLock CPUwl;
	private PowerManager.WakeLock Screenwl;
	private SharedPreferences mSharedPreferences;
	public static final String PREFS_STATE = "AL_State";
	//RingtoneManager mRingtoneManager;
	
	private boolean forceFire = false;
	
	/// Hlídáme pohyb až poté, co přijde správný intent
	private boolean sActivated = false;
	
	/// Následující proměnné jsou inicializovány z uživatelského nastavení
	private boolean sAccel;
	private boolean sAlarm;
	private boolean sSMS;
	private Ringtone mRtone;
	private int sAccSensitivity;
	private String sAlarmSMS;
	private String sLocSMS;
	private boolean firstTime = true;

	private float v1;
	private float v2;
	private float v3;
	
	private final double treshold = 0.5; 
	private float lastPos = 0;
	private int state;
	
	private AudioManager mAudioManager;
	private int previousVolume;
	
	private void startRinging() {
		if (forceFire == false){
			// Save actual ringing volume
			previousVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
			// Set ringing volume to max
			mAudioManager.setStreamVolume(AudioManager.STREAM_RING,
					mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING), 0);
			/** Acquire a screen wake lock */
			Screenwl.acquire(30 * 1000);	// wake up for 30 seconds and a little bit beyond
				//(ON_AFTER_RELEASE)
		} else {
			;
		}
		// Set flag
		forceFire = true;
		
	}
	
	private void stopRinging() {
		if (forceFire == true){
			mAudioManager.setStreamVolume(AudioManager.STREAM_RING,
					previousVolume, 0);
		} else {
			;
		}
		// UnSet flag
		forceFire = false;
	}
	
	public void onSensorChanged(SensorEvent event) {
	//Log.d("schanged", Float.toString(values[0])+Float.toString( values[1])+Float.toString(values[2]));
	//Toast.makeText(this, Float.toString(values[0])+Float.toString( values[1])+Float.toString(values[2]), Toast.LENGTH_SHORT).show();
		if(sActivated){
			if(firstTime){
				v1 = event.values[0];
				v2 = event.values[1];
				v3 = event.values[2];
				java.lang.Math.sqrt((double) ((event.values[0]*event.values[0]) + (event.values[1]*event.values[1]) + (event.values[2]*event.values[2])));
				firstTime = false;
			}
			//if (Math.abs(lastPos - event.timestamp) > time_treshold) {
//				Log.d("", "prošli jsme tresholdem");
				//FIXME: Better tresholding, detect velocity/distance perhaps
			   	if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
			   		Log.d("", "je to accelerometr");
						double size = Math.sqrt(Math.pow(event.values[0],2) + Math.pow(event.values[1], 2) + Math.pow(event.values[2], 2));
						if (Math.abs(v1 - event.values[0]) > treshold){
							startRinging();
						 	
						} else {
							//v1 = event.values[0];
						}
						if (Math.abs(v2 - event.values[1]) > treshold){
							startRinging();
						 	
						} else {
							//v2 = event.values[1];
						}
						if (Math.abs(v3 - event.values[2]) > treshold){
							startRinging();
						 	
						} else {
							//v3 = event.values[2];
						}
						//if (Math.abs(vs - size) > treshold){
						//	forceFire = true;
						// 	
						//} else {
						//	//vs = size;
						//}
			   	}
			   	lastPos = event.timestamp;
			//}
		}
		Log.d("", "SensorChanged");
		if(!mRtone.isPlaying()) {
			//Log.d("", "Is not playing");
			//Toast.makeText(this, "znovu", Toast.LENGTH_SHORT).show();
			if(forceFire && sActivated){
//				Log.d("", "Hrajeme!:");
				mRtone.play();
			}
		} else {
			//Log.d("", "IS playing");
			return;
		}
		
	}

	/** Called when the service is first created. */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("", "onCtreate");
        /// Notifikujeme uivatele
        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        notifyStart();
        
        /// Načteme preference
        Log.d("", "Načteme preference");
        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext());
	    //mRingtoneManager = new RingtoneManager(this.getApplicationContext());
   	    loadSettings();
   	    Log.d("", "po Load settongs");
		//startService(new Intent(AntiLapka.this, AntiLapkaService.class));
		//SystemClock.sleep(5000);
		// spusť aktivitu, kde se nastaví, které senzory budou aktivní
     
		//...
	    // odkomentováno z důvodu použití SensorSimulator
	    // použijte tento kód, pokud nasazujete na reálné zařízení
	       mSensorManager =
	          (SensorManager) getSystemService(SENSOR_SERVICE); 
	 //
	    // začátek inicializačního kódu pro SensorSimulator
	    // před voláním simulátoru musí být nastaven content
	    // resolver, který používá sám simulátor
	 //   Hardware.mContentResolver = getContentResolver(); 
	 
	    // nastav sensor manager, aby používal sensor simulátor
	  //  mSensorManager = (SensorManager) new SensorManagerSimulator(
	     //   (SensorManager) getSystemService(SENSOR_SERVICE)); 
	 //

	    // konec inicializačního kódu pro SensorSimulator
	    //...
	 //   
	   // SensorManagerSimulator.connectSimulator();
	    
	    // registruj listenery pro senzor akcelerace a orientace
	       mSensorManager.registerListener(this,
	    		   mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME);
	    lastPos = SystemClock.elapsedRealtime();
	    
	    SharedPreferences state = getSharedPreferences(PREFS_STATE, 0);
	    SharedPreferences.Editor editor = state.edit();
	    editor.putBoolean("service_active", true);

	    // Don't forget to commit your edits!!!
	    editor.commit();
 
	    mAudioManager =
	          (AudioManager) getSystemService(AUDIO_SERVICE); 
	    mPowerManager =
	    	(PowerManager) getSystemService(POWER_SERVICE);
	    CPUwl =
			mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Activated");
	    Screenwl =
			mPowerManager.newWakeLock(
					PowerManager.SCREEN_BRIGHT_WAKE_LOCK 
					| PowerManager.ON_AFTER_RELEASE 
					| PowerManager.ACQUIRE_CAUSES_WAKEUP
					,"Ringing");
    
    }
    

    public void onStart(Intent intent, int startid){
    	Log.d("onStart", "Jedem");
    		
		///Zpracuje předaný intent
    	Bundle args = intent.getExtras();
    	if(args == null) return;
    	
    	///Reaguje na parametry
    	if(args.containsKey("cz.dnk.gug.android.antilapka.Activate")){
    		Log.d("onStart", "Obsahuje Activate");
    		if(args.getBoolean("cz.dnk.gug.android.antilapka.Activate", false)){
    			firstTime = true;
    			forceFire = false;
    			sActivated = true;
    			/** We need CPU for movement detection */
    			if(!CPUwl.isHeld())	CPUwl.acquire();	// hope it gets released in all cases. Cannot set timelimit
    			
    		} else {
    			sActivated = false;
    			firstTime = true;
    			stopRinging();
    			if(CPUwl.isHeld())	CPUwl.release();
    		}
    	}
    	if(args.containsKey("cz.dnk.gug.android.antilapka.loadSettings")){
    		if(args.getBoolean("cz.dnk.gug.android.antilapka.loadSettings", false)){
    			loadSettings();
    		}
    	}
    	if(args.containsKey("cz.dnk.gug.android.antilapka.Fire")){
    		if(args.getBoolean("cz.dnk.gug.android.antilapka.Fire", false)){
    			sActivated = true;
    			startRinging();
    		}
    	}
    	if(args.containsKey("cz.dnk.gug.android.antilapka.Plugged")){
    		/** The power cord has been plugged */
    		if(args.getBoolean("cz.dnk.gug.android.antilapka.Plugged", true)){
    			//Play sound "armed"
    			MediaPlayer mp = MediaPlayer.create(this.getApplicationContext(), R.raw.armed);
    		    mp.start(); 
    		    
    		    //Set state to "Armed"
    		    this.state = ARMED;
    		}
    	}
    	if(args.containsKey("cz.dnk.gug.android.antilapka.UnPlugged")){
    		if(args.getBoolean("cz.dnk.gug.android.antilapka.UnPlugged", true)){
    			if(this.state == ARMED){
    				MediaPlayer mp2 = MediaPlayer.create(this.getApplicationContext(), R.raw.disarmed);
        		    mp2.start();
    			}
    		}
    	}
    	
    }
    

    public void onStop(){


    }
    
    @Override
    public void onDestroy(){
    	super.onDestroy();
    	/** Check the CPU wake-lock */
    	if(CPUwl.isHeld())	CPUwl.release();
    	
    	/** Cancel the "Antilapka running" notification */
    	mNM.cancel(R.string.service_started);
    	
    	/** Toast the user */
    	Toast.makeText(this, R.string.service_stopped, Toast.LENGTH_SHORT).show();
    	
   	  //  mSensorManager.unregisterListener(this);
   	    Log.d("", "Odregistrováno, skončeno");
   	    //mEnde = true;
   	    
   	    SharedPreferences settings = getSharedPreferences(PREFS_STATE, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean("service_active", false);

        // Don't forget to commit your edits!!!
        editor.commit();

   	    
   	    
    }
    
    
    /**
     * Přidá naši aktivitu to takového toho rolovacího tentononc nahoře vlevo
     */
    private void notifyStart() {
        
        CharSequence text = getText(R.string.service_started);

        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.icon, text,
                System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, AntiLapka.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, getText(R.string.service_label),
                       text, contentIntent);

        // Send the notification.
        // We use a layout id because it is a unique number.  We use it later to cancel.
        mNM.notify(R.string.service_started, notification);
    }
    
    /**
     * Načte nastavení
     * 
     * Volá se při onCreate() a při onStart když přijde příslušný intent
     * 
     * 
     */
    private void loadSettings(){
    	Log.d("", "Načitam...");
    	/// Je alarmování při pohybu zapnuté?
    	sAlarm = mSharedPreferences.getBoolean("pref_Alarm", true);
    	Log.d("1", "Načitam...");
    	/// Získá buď uživatelem vybraný alarm, nebo vrátí defaultní
    	Uri songURI = RingtoneManager.getValidRingtoneUri(getApplicationContext());
    	
    	String song = mSharedPreferences.getString(
    			"pref_Ringtone", "ERROR");
    	if(song != "ERROR"){
    		songURI = Uri.parse(song);
    	}
    	mRtone = RingtoneManager.getRingtone(this.getApplicationContext(), songURI);
		Log.d("2", "Načitam...");
		/// Je akcelerometr povolený?
		sAccel = mSharedPreferences.getBoolean(
				"pref_Accel", true);
		Log.d("3", "Načitam...");
		/// Získá požadovanou přesnost akcelerometru, jinak nastaví přesnost vysokou/herní
		sAccSensitivity = mSharedPreferences.getInt(
				"pref_Accel_Citlivost", SensorManager.SENSOR_DELAY_GAME);
		Log.d("4", "Načitam...");
		/// Je povoleno ovládání přes SMS?
		sSMS = mSharedPreferences.getBoolean(
				"pref_SMS", false);
		Log.d("5", "Načitam...");
		/// SMS pro alarm
		sAlarmSMS = mSharedPreferences.getString(
				"pref_Alarm_SMS", null);
		Log.d("6", "Načitam...");
		///SMS pro polohu
		sLocSMS = mSharedPreferences.getString(
				"pref_Loc_SMS", null);
		Log.d("Ende", "Načitam...");
    }

	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
}
